package com.quwan.manager.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.quwan.common.BaseService;
import com.quwan.common.ImMsgType;
import com.quwan.common.enums.DeviceEnum;
import com.quwan.common.enums.SystemMsgEnum;
import com.quwan.common.form.PushForm;
import com.quwan.common.query.LambdaQueryWrapperX;
import com.quwan.common.result.PageResult;
import com.quwan.common.result.PushDTO;
import com.quwan.common.service.PushService;
import com.quwan.component.TencentComponent;
import com.quwan.config.yml.ImConfig;
import com.quwan.entity.*;
import com.quwan.manager.service.SystemMessageService;
import com.quwan.mapper.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author quan
 * @date 2021-11-22 1:28
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class SystemMessageServiceImpl extends BaseService implements SystemMessageService {
    private static final int PUSH_MSG_MAX = 500;
    private final TSystemPushMsgMapper systemPushMsgMapper;
    private final TMessageAccountMapper messageAccountMapper;
    private final TencentComponent tencentComponent;
    private final TMemberMapper memberMapper;
    private final ImConfig imConfig;
    private final TMsgRecordMapper msgRecordMapper;
    private final PushService pushService;
    private final TMessageMapper messageMapper;

    @Autowired
    @Qualifier("asyncThread")
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public void createMsg(TAdmin admin, String body, String type) {

        int messageRow = systemPushMsgMapper.insert(
                new TSystemPushMsg()
                        .setContent(body)
                        .setCreateBy(admin.getLoginName())
                        .setType(Integer.parseInt(type))
        );

        if (messageRow == 1) {
            TMessageAccount pushAcc = messageAccountMapper.selectOne(
                    new LambdaQueryWrapper<TMessageAccount>()
                            .select(TMessageAccount::getAccount)
                            .eq(TMessageAccount::getType, type)
                            .eq(TMessageAccount::getStatus, 1)
            );
            if (pushAcc == null)
                return;

            CompletableFuture.runAsync(() -> {
                int idx = 1;
                int pageNo = 0;
                boolean hasMore = false;
                do {
                    List<TMember> list =
                            memberMapper
                                    .selectList(
                                            new LambdaQueryWrapper<TMember>()
                                                    .select(TMember::getId)
                                                    .eq(TMember::getStatus, 1)
                                                    .orderByDesc(TMember::getServiceLevel)
                                                    .last(new StringBuffer(" limit ")
                                                            .append(pageNo)
                                                            .append(" , ")
                                                            .append(PUSH_MSG_MAX).toString())
                                    );
                    List<String> ids = list.stream().map(m -> m.getId() + "").collect(Collectors.toList());
                    hasMore = list.size() == PUSH_MSG_MAX;
                    if (CollectionUtils.isNotEmpty(ids)) {

                        String resJson = tencentComponent.batchPushMsg(2, pushAcc.getAccount(), ids, ImMsgType.text.getCode(), body);
                        JSONObject resObj = JSONObject.parseObject(resJson);
                        String errorCode = resObj.getString("ErrorCode");
                        if (!"0".equals(errorCode)) {
                            log.error("消息发送失败：：{}", resJson);
                            return;
                        }
                        pageNo = (++idx - 1) * PUSH_MSG_MAX;
                    }


                }
                while (hasMore);

            }, taskExecutor);
        }


    }


    @Override
    public void createPersonalMsg(TAdmin admin, String mId, String body) {
        Boolean success = tencentComponent.singlePushMsg(2, imConfig.getPersonalAcc(), "站内消息", mId, ImMsgType.text.getCode(), body);
        if (!success)
            log.info("个人消息发送失败：：{},content::{}", mId, body);
        else {
            int messageRow = systemPushMsgMapper.insert(
                    new TSystemPushMsg()
                            .setContent(body)
                            .setCreateBy(admin.getLoginName())
                            .setType(SystemMsgEnum.PERSONAL.getType())
                            .setReceiverId(mId)

            );
            if (messageRow != 1)
                log.info("个人消息保存失败：：{},content::{}", mId, body);
        }

    }

    @Override
    public PageResult<TSystemPushMsg> msgList(int pageNo, int pageSize, String type, String mId) {
        Page<TSystemPushMsg> page = systemPushMsgMapper
                .selectPage(
                        new Page<>(pageNo, pageSize),
                        new LambdaQueryWrapper<TSystemPushMsg>()
                                .eq(TSystemPushMsg::getType, type)
                                .eq(SystemMsgEnum.getByType(Integer.parseInt(type)).getType() == 5, TSystemPushMsg::getReceiverId, mId)
                                .orderByDesc(TSystemPushMsg::getUpdTime)

                );
        return new PageResult<TSystemPushMsg>()
                .setRecords(page.getRecords())
                .setTotal(page.getTotal())
                .setCurrent(page.getCurrent())
                .setSize(page.getSize())
                .setPages(page.getPages());


    }

    @Override
    public boolean delSystemMsg(Long id) {
        return systemPushMsgMapper.deleteById(id) == 1;
    }

    @Override
    public PageResult<TMsgRecord> getChatRecordList(int pageNo, int pageSize, String sender, String receiver, String sessionKey, String content, Integer status) {
        LambdaQueryWrapperX<TMsgRecord> query = new LambdaQueryWrapperX<TMsgRecord>().
                eqIfPresent(TMsgRecord::getSender, sender)
                .eqIfPresent(TMsgRecord::getReceiver, receiver)
                .eqIfPresent(TMsgRecord::getSessionKey, sessionKey)
                .eqIfPresent(TMsgRecord::getStatus, status)
                .likeIfPresent(TMsgRecord::getMsgContent, content)
                .orderByDesc(TMsgRecord::getMsgTime);

        Page<TMsgRecord> res = msgRecordMapper.selectPage(new Page<>(pageNo, pageSize), query);


        return new PageResult<TMsgRecord>()
                .setPages(res.getPages())
                .setTotal(res.getTotal())
                .setCurrent(res.getCurrent())
                .setSize(res.getSize())
                .setRecords(res.getRecords().stream().peek(m -> m.setTime(LocalDateTime.ofEpochSecond(m.getMsgTime(), 0, ZoneOffset.ofHours(8)))).collect(Collectors.toList()));

    }

    @Override
    public void changeChatRecordStatus(List<Long> ids, Integer status) {
        if (CollectionUtils.isEmpty(ids) || status == null)
            return;
        msgRecordMapper.update(null, new LambdaUpdateWrapper<TMsgRecord>().set(TMsgRecord::getStatus, status).in(TMsgRecord::getId, ids));
    }

    @Override
    public void pushRealNamePersonalMsg(TAdmin admin, String idStatus, String sex, String body) {

        List<TMember> members = memberMapper.selectList(
                new LambdaQueryWrapper<TMember>()
                        .select(TMember::getId)
                        .eq(!"-1".equals(sex), TMember::getGender, sex)
                        .ge(TMember::getIdStatus, idStatus));
        List<TSystemPushMsg> insertMsg = members
                .stream()
                .map(member -> {
                            tencentComponent.singlePushMsg(2, imConfig.getPersonalAcc(), "站内消息", member.getId().toString(), ImMsgType.text.getCode(), body);
                            return new TSystemPushMsg()
                                    .setContent(body)
                                    .setCreateBy(admin.getLoginName())
                                    .setType(SystemMsgEnum.PERSONAL.getType())
                                    .setUpdBy(admin.getLoginName())
                                    .setUpdTime(LocalDateTime.now())
                                    .setCreateTime(LocalDateTime.now())
                                    .setReceiverId(member.getId().toString());
                        }
                )
                .collect(Collectors.toList());
        if (!insertMsg.isEmpty())
            systemPushMsgMapper.insertBatchSomeColumn(insertMsg);

    }

    @Override
    public void pushOfflineMsg(TAdmin admin, String body,String title) {
        PushForm pushForm = new PushForm(title, body, null, Maps.newHashMap());
       // PushDTO pushDTO = pushService.pushAndroidAll(pushForm);
        PushDTO pushDTO = pushService.pushIosAll(pushForm);

        TMessage message =
                new TMessage()
                        .setUserId(0l)
                        .setBody(body)
                        .setTitle(title)
                        .setStatus((byte) 1)
                        .setType((byte) 1)
                        .setCreateUserId(admin.getId())
                        .setPlatform(DeviceEnum.ALL.getType().byteValue())
                        .setMessageId(pushDTO.getPushId());
        messageMapper.insert(message);
    }

    @Override
    public PageResult<TMessage> offlineMsgList(int pageNo, int pageSize) {
        Page<TMessage> res = messageMapper.selectPage(new Page<>(pageNo, pageSize), new LambdaUpdateWrapper<TMessage>().eq(TMessage::getType, 1).orderByDesc(TMessage::getCreateTime));
        return  new PageResult<TMessage>().setRecords(res.getRecords()).setSize(res.getSize()).setCurrent(res.getCurrent()).setTotal(res.getTotal()).setPages(res.getPages());
    }


}
